﻿Imports System.Math
Imports System.Windows.Controls.Canvas

Public Class shpEditor

#Region "events declaration"
    Public Event Clear(ByVal sender As Object)
    Public Event FocusChanged(ByVal sender As Object)
    Public Event DragChanged(ByVal sender As Object)
    Public Event CreatedBlock(ByVal sender As Object, ByVal control As shpBlock)
    Public Event DeletedBlock(ByVal sender As Object, ByVal control As shpBlock)
    Public Event CreatedActivator(ByVal sender As Object, ByVal control As clsActivator)
    Public Event DeletedActivator(ByVal sender As Object, ByVal control As clsActivator)
    Public Event CreatedEvent(ByVal sender As Object, ByVal control As clsEvent)
    Public Event DeletedEvent(ByVal sender As Object, ByVal control As clsEvent)
    Public Event CreatedInput(ByVal sender As Object, ByVal control As clsInput)
    Public Event DeletedInput(ByVal sender As Object, ByVal control As clsInput)
    Public Event CreatedOutput(ByVal sender As Object, ByVal control As clsOutput)
    Public Event DeletedOutput(ByVal sender As Object, ByVal control As clsOutput)
    Public Event CreatedConnector(ByVal sender As Object, ByVal control As shpConnector)
    Public Event DeletedConnector(ByVal sender As Object, ByVal control As shpConnector)
    Public Event ConnectPorts(ByVal sender As Object, ByVal Port1 As shpPort, ByVal Port2 As shpPort)
    Public Event DisconnectPorts(ByVal sender As Object, ByVal Port1 As shpPort, ByVal Port2 As shpPort)
    Public Event UnloadedBlock(ByVal sender As Object, ByVal control As shpBlock)
    Public Event UnloadedActivator(ByVal sender As Object, ByVal control As clsActivator)
    Public Event UnloadedEvent_(ByVal sender As Object, ByVal control As clsEvent)
    Public Event UnloadedInput(ByVal sender As Object, ByVal control As clsInput)
    Public Event UnloadedOutput(ByVal sender As Object, ByVal control As clsOutput)
    Public Event EditorDoubleClick(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
    Public Event BlockDoubleClick(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
    Public Event ActivatorDoubleClick(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
    Public Event EventDoubleClick(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
    Public Event InputDoubleClick(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
    Public Event OutputDoubleClick(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
#End Region

    Private m_Type As Byte
    Private m_PntCursor As Point
    Private m_Objects As Long
    Private m_Drag As Object
    Private m_Focus As Object
    Private m_ZoomX As Double
    Private m_ZoomY As Double

    Private Blocks As New Collection
    Private Activators As New Collection
    Private Events As New Collection
    Private Inputs As New Collection
    Private Outputs As New Collection
    Private Connectors As New Collection

#Region "properties"
    ' Тип объекта
    Public ReadOnly Property Type() As Integer
        Get
            Return m_Type
        End Get
    End Property
    ' Коллекция блоков
    Public ReadOnly Property GetBlocks() As Collection
        Get
            GetBlocks = Blocks
        End Get
    End Property
    ' Коллекция activators
    Public ReadOnly Property GetActivators() As Collection
        Get
            GetActivators = Activators
        End Get
    End Property
    ' Коллекция events
    Public ReadOnly Property GetEvents() As Collection
        Get
            GetEvents = Events
        End Get
    End Property
    ' Коллекция inputs
    Public ReadOnly Property GetInputs() As Collection
        Get
            GetInputs = Inputs
        End Get
    End Property
    ' Коллекция outputs
    Public ReadOnly Property GetOutputs() As Collection
        Get
            GetOutputs = Outputs
        End Get
    End Property
    ' Коллекция connectors
    Public ReadOnly Property GetConnectors() As Collection
        Get
            GetConnectors = Connectors
        End Get
    End Property
    ' Масштаб по X
    Public ReadOnly Property ZoomX() As Double
        Get
            Return m_ZoomX
        End Get
    End Property
    ' Масштаб по Y
    Public ReadOnly Property ZoomY() As Double
        Get
            Return m_ZoomY
        End Get
    End Property
    ' Объект, обладающий фокусом
    Public Property FocusObject() As Object
        Get
            Return m_Focus
        End Get
        Friend Set(value As Object)
            If value IsNot m_Focus Then
                m_Focus = value
                RaiseEvent FocusChanged(m_Focus)
            End If
        End Set
    End Property
    ' Перетаскиваемый объект
    Public Property DragObject() As Object
        Get
            Return m_Drag
        End Get
        Friend Set(value As Object)
            If value IsNot m_Drag Then
                m_Drag = value
                RaiseEvent DragChanged(m_Drag)
            End If
        End Set
    End Property

#End Region
    ' Доавление блока
    Public Function AddBlock(Optional X As Long = c_PortWidth, Optional Y As Long = c_PortHeight) As shpBlock
        Dim shp As shpBlock, key As String
        key = UniqueKey()
        shp = New shpBlock(Me, key)
        Blocks.Add(shp, key)
        Editor.Children.Add(shp)
        shp.MoveShape(X, Y)
        shp.Visibility = Windows.Visibility.Visible
        AddBlock = shp
        shp.Focus()
        AddHandler shp.CreatedActivator, AddressOf shpBlock_CreatedActivator
        AddHandler shp.DeletedActivator, AddressOf shpBlock_DeletedActivator
        AddHandler shp.CreatedEvent, AddressOf shpBlock_CreatedEvent
        AddHandler shp.DeletedEvent, AddressOf shpBlock_DeletedEvent
        AddHandler shp.CreatedInput, AddressOf shpBlock_CreatedInput
        AddHandler shp.DeletedInput, AddressOf shpBlock_DeletedInput
        AddHandler shp.CreatedOutput, AddressOf shpBlock_CreatedOutput
        AddHandler shp.DeletedOutput, AddressOf shpBlock_DeletedOutput
        AddHandler shp.UnloadedActivator, AddressOf shpBlock_UnloadedActivator
        AddHandler shp.UnloadedEvent_, AddressOf shpBlock_UnloadedEvent
        AddHandler shp.UnloadedInput, AddressOf shpBlock_UnloadedInput
        AddHandler shp.UnloadedOutput, AddressOf shpBlock_UnloadedOutput
        AddHandler shp.Unloaded, AddressOf shpBlock_Unloaded
        AddHandler shp.ActivatorDoubleClick, AddressOf shpActivator_DoubleClick
        AddHandler shp.EventDoubleClick, AddressOf shpEvent_DoubleClick
        AddHandler shp.InputDoubleClick, AddressOf shpInput_DoubleClick
        AddHandler shp.OutputDoubleClick, AddressOf shpOutput_DoubleClick
        AddHandler shp.MouseDoubleClick, AddressOf shpBlock_DoubleClick
        RaiseEvent CreatedBlock(Me, shp)
    End Function
    ' Добавление activator
    Public Function AddActivator() As clsActivator
        Dim shp As clsActivator, key As String
        key = UniqueKey()
        shp = New clsActivator(Me, key)
        Activators.Add(shp, key)
        Editor.Children.Add(shp)
        DrawActivators()
        shp.Visibility = Windows.Visibility.Visible
        AddActivator = shp
        shp.Focus()
        AddHandler shp.Unloaded, AddressOf shpActivator_Unloaded
        AddHandler shp.PortDoubleClick, AddressOf shpActivator_DoubleClick
        RaiseEvent CreatedActivator(Me, shp)
    End Function
    ' Добавление event
    Public Function AddEvent() As clsEvent
        Dim shp As clsEvent, key As String
        key = UniqueKey()
        shp = New clsEvent(Me, key)
        Events.Add(shp, key)
        Editor.Children.Add(shp)
        DrawEvents()
        shp.Visibility = Windows.Visibility.Visible
        AddEvent = shp
        shp.Focus()
        AddHandler shp.Unloaded, AddressOf shpEvent_Unloaded
        AddHandler shp.PortDoubleClick, AddressOf shpEvent_DoubleClick
        RaiseEvent CreatedEvent(Me, shp)
    End Function
    ' Доавление input
    Public Function AddInput() As clsInput
        Dim shp As clsInput, key As String
        key = UniqueKey()
        shp = New clsInput(Me, key)
        Inputs.Add(shp, key)
        Editor.Children.Add(shp)
        DrawInputs()
        shp.Visibility = Windows.Visibility.Visible
        AddInput = shp
        shp.Focus()
        AddHandler shp.Unloaded, AddressOf shpInput_Unloaded
        AddHandler shp.PortDoubleClick, AddressOf shpInput_DoubleClick
        RaiseEvent CreatedInput(Me, shp)
    End Function
    ' Добавление output
    Public Function AddOutput() As clsOutput
        Dim shp As clsOutput, key As String
        key = UniqueKey()
        shp = New clsOutput(Me, key)
        Outputs.Add(shp, key)
        Editor.Children.Add(shp)
        DrawOutputs()
        shp.Visibility = Windows.Visibility.Visible
        AddOutput = shp
        shp.Focus()
        AddHandler shp.Unloaded, AddressOf shpOutput_Unloaded
        AddHandler shp.PortDoubleClick, AddressOf shpOutput_DoubleClick
        RaiseEvent CreatedOutput(Me, shp)
    End Function
    ' Добавление соединителя
    Public Function AddConnector(ByVal points() As Point) As Object
        Dim shp As shpConnector, key As String
        key = UniqueKey()
        shp = New shpConnector(Me, key, points)
        Connectors.Add(shp, key)
        Editor.Children.Add(shp)
        shp.Visibility = Windows.Visibility.Visible
        AddConnector = shp
        shp.Focus()
        AddHandler shp.ConnectPorts, AddressOf shpConnector_ConnectPorts
        AddHandler shp.DisconnectPorts, AddressOf shpConnector_DisconnectPorts
        RaiseEvent CreatedConnector(Me, shp)
    End Function
    ' Удаление всех объектов / удаление объекта (блок, порт, коннектор)
    Public Sub Remove(ByVal shp As Object)
        Select Case shp.Type
            Case c_Editor
                Editor.Children.Clear()
                Editor.Children.Add(shpFrame)
                Blocks.Clear()
                Activators.Clear()
                Events.Clear()
                Inputs.Clear()
                Outputs.Clear()
                Connectors.Clear()
                m_Objects = 0
                RaiseEvent Clear(Me)
            Case c_Block
                Editor.Children.Remove(shp)
                Blocks.Remove(shp.key)
                RaiseEvent DeletedBlock(Me, shp)
            Case c_Activator
                Editor.Children.Remove(shp)
                Activators.Remove(shp.key)
                DrawActivators()
                RaiseEvent DeletedActivator(Me, shp)
            Case c_Input
                Editor.Children.Remove(shp)
                Inputs.Remove(shp.key)
                DrawInputs()
                RaiseEvent DeletedInput(Me, shp)
            Case c_Output
                Editor.Children.Remove(shp)
                Outputs.Remove(shp.key)
                DrawOutputs()
                RaiseEvent DeletedOutput(Me, shp)
            Case c_Event
                Editor.Children.Remove(shp)
                Events.Remove(shp.key)
                DrawEvents()
                RaiseEvent DeletedEvent(Me, shp)
            Case c_Connector
                Editor.Children.Remove(shp)
                Connectors.Remove(shp.key)
                RaiseEvent DeletedConnector(Me, shp)
        End Select
    End Sub
    ' Импорт из XML
    Public Function Import(ByVal content As String) As Boolean
        Dim xdoc As XDocument
        On Error Resume Next
        xdoc = XDocument.Parse(content)
        If xdoc IsNot Nothing Then
            Return XMLPack(Me, content)
        Else
            Return False
        End If
    End Function
    ' Экспорт из XML
    Public Function Export() As String
        Return XMLParse(Me)
    End Function

    Private Sub DrawBlocks()
        Dim shp As shpBlock
        For Each shp In Blocks
            shp.Block.Width = shp.nWidth * ZoomX
            shp.Block.Height = shp.nHeight * ZoomY
            SetLeft(shp, shp.nLeft * ZoomX)
            SetTop(shp, shp.nTop * ZoomY)
        Next shp
    End Sub

    Private Sub DrawActivators()
        Dim i As Long, shp As clsActivator, cnt As Long
        cnt = Activators.Count + 1
        For Each shp In Activators
            i += 1
            shp.MoveShape(0, i * (c_EditorHeight / cnt) * ZoomY - c_PortHeight / 2)
        Next shp
    End Sub

    Private Sub DrawEvents()
        Dim i As Long, shp As clsEvent, cnt As Long
        cnt = Events.Count + 1
        For Each shp In Events
            i += 1
            shp.MoveShape(c_EditorWidth * ZoomX - c_PortWidth, i * (c_EditorHeight / cnt) * ZoomY - c_PortHeight / 2)
        Next shp
    End Sub

    Private Sub DrawInputs()
        Dim i As Long, shp As clsInput, cnt As Long
        cnt = Inputs.Count + 1
        For Each shp In Inputs
            i += 1
            shp.MoveShape(i * (c_EditorWidth / cnt) * ZoomX - c_PortWidth / 2, 0)
        Next shp
    End Sub

    Private Sub DrawOutputs()
        Dim i As Long, shp As clsOutput, cnt As Long
        cnt = Outputs.Count + 1
        For Each shp In Outputs
            i += 1
            shp.MoveShape(i * (c_EditorWidth / cnt) * ZoomX - c_PortWidth / 2, c_EditorHeight * ZoomY - c_PortHeight)
        Next shp
    End Sub

    Private Sub DrawConnectors()
        Dim shp As Object
        For Each shp In Connectors
            shp.Zoom()
        Next shp
    End Sub

    Private Sub DrawFrame()
        shpFrame.Width = Width - c_PortWidth
        shpFrame.Height = Height - c_PortHeight
    End Sub

    Private Sub Draw()
        DrawFrame()
        DrawConnectors()
        DrawBlocks()
        DrawActivators()
        DrawEvents()
        DrawInputs()
        DrawOutputs()
    End Sub

    'Генерация уникального ключа
    Private Function UniqueKey() As String
        m_Objects += 1
        UniqueKey = m_Objects.ToString
    End Function

#Region "events"
    Private Sub shpEditor_Initialized(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Initialized
        m_Type = c_Editor
        m_ZoomX = 1 : m_ZoomY = 1
    End Sub

    Private Sub shpEditor_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Loaded
        m_ZoomX = Width / c_EditorWidth
        m_ZoomY = Height / c_EditorHeight
        SetLeft(shpFrame, c_PortWidth / 2)
        SetTop(shpFrame, c_PortHeight / 2)
    End Sub

    Private Sub shpEditor_SizeChanged(ByVal sender As Object, ByVal e As SizeChangedEventArgs) Handles Me.SizeChanged
        If Width < c_EditorWidth Then
            Width = c_EditorWidth
        Else
            m_ZoomX = Width / c_EditorWidth
        End If
        If Height < c_EditorHeight Then
            Height = c_EditorHeight
        Else
            m_ZoomY = Height / c_EditorHeight
        End If
        Draw()
    End Sub

    Private Sub shpEditor_MouseDown(ByVal sender As Object, ByVal e As MouseButtonEventArgs) Handles Me.MouseDown
        Dim x As Integer, y As Integer
        x = e.GetPosition(Me).X : y = e.GetPosition(Me).Y
        m_PntCursor.X = x : m_PntCursor.Y = y
        If e.OriginalSource.Name = "shpFrame" Then
            FocusObject = Me
            Focus()
        End If
    End Sub

    Private Sub shpEditor_MouseLeftButtonUp(ByVal sender As Object, ByVal e As MouseButtonEventArgs) Handles Me.MouseLeftButtonUp
        DragObject = Nothing
    End Sub

    Private Sub shpEditor_MouseLeftButtonDown(ByVal sender As Object, ByVal e As MouseButtonEventArgs) Handles Me.MouseLeftButtonDown

    End Sub

    Private Sub shpEditor_MouseDoubleClick(ByVal sender As Object, ByVal e As MouseButtonEventArgs) Handles Me.MouseDoubleClick
        If e.OriginalSource.Name = "shpFrame" Then
            RaiseEvent EditorDoubleClick(Me, e)
        End If
    End Sub

    Private Sub shpEditor_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles Me.MouseMove
        Dim x As Integer, y As Integer, wid As Integer, hei As Integer, boundX As Integer, boundY As Integer
        If DragObject IsNot Nothing Then
            If TryCast(DragObject, clsHolder) IsNot Nothing Then
                boundX = c_PortWidth / 2 - c_HolderWidth / 2 : boundY = c_PortHeight / 2 - c_HolderHeight / 2
            ElseIf TryCast(DragObject, shpBlock) IsNot Nothing Then
                boundX = c_PortWidth : boundY = c_PortHeight
            End If
            x = e.GetPosition(Me).X - DragObject.ClickX : y = e.GetPosition(Me).Y - DragObject.ClickY
            wid = DragObject.Shape.ActualWidth : hei = DragObject.Shape.ActualHeight
            If x < boundX Then
                x = boundX
            ElseIf x > Width - boundX - wid Then
                x = Width - boundX - wid
            End If
            If y < boundY Then
                y = boundY
            ElseIf y > Height - boundY - hei Then
                y = Height - boundY - hei
            End If
            DragObject.MoveShape(x, y)
        End If
    End Sub

    Private Sub shpEditor_KeyDown(ByVal sender As Object, ByVal e As KeyEventArgs) Handles Me.KeyDown
        If FocusObject Is Me And Keyboard.Modifiers = ModifierKeys.Control Then
            Select Case e.Key
                Case Input.Key.B
                    Dim blk As shpBlock
                    blk = AddBlock()
                    blk.AddActivator()
                    blk.AddEvent()
                    blk.AddInput()
                    blk.AddOutput()
                Case Input.Key.A
                    AddActivator()
                Case Input.Key.E
                    AddEvent()
                Case Input.Key.I
                    AddInput()
                Case Input.Key.O
                    AddOutput()
                Case Input.Key.C
                    AddConnector(New Point() {New Point(c_PortWidth, c_PortHeight)})
            End Select
        End If
    End Sub

    Private Sub itmBlock_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        Dim shp As shpBlock
        shp = AddBlock(m_PntCursor.X, m_PntCursor.Y)
        shp.AddActivator()
        shp.AddEvent()
        shp.AddInput()
        shp.AddOutput()
    End Sub

    Private Sub itmActivator_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        AddActivator()
    End Sub

    Private Sub itmEvent_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        AddEvent()
    End Sub

    Private Sub itmInput_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        AddInput()
    End Sub

    Private Sub itmOutput_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        AddOutput()
    End Sub

    Private Sub itmConnector_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        AddConnector(New Point() {New Point(m_PntCursor.X, m_PntCursor.Y)})
    End Sub

    Private Sub itmRemove_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        Dim res As MessageBoxResult
        res = MessageBox.Show("All objects will be removed.", "Confirmation", MessageBoxButton.YesNo, MessageBoxImage.Question)
        If res = MessageBoxResult.Yes Then
            Remove(Me)
        End If
    End Sub

    Private Sub itmExport_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        Dim dlg As New Microsoft.Win32.SaveFileDialog()
        If dlg.ShowDialog() = True Then
            XDocument.Parse(Export()).Save(dlg.FileName, SaveOptions.None)
        End If
    End Sub

    Private Sub itmImport_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        Dim dlg As New Microsoft.Win32.OpenFileDialog()
        dlg.DefaultExt = ".xml"
        If dlg.ShowDialog() = True Then
            Import(IO.File.ReadAllText(dlg.FileName))
        End If
    End Sub
#End Region

#Region "childs events"

    Private Sub shpBlock_Unloaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
        RaiseEvent UnloadedBlock(Me, sender)
    End Sub

    Private Sub shpActivator_Unloaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
        RaiseEvent UnloadedActivator(Me, sender)
    End Sub

    Private Sub shpEvent_Unloaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
        RaiseEvent UnloadedEvent_(Me, sender)
    End Sub

    Private Sub shpInput_Unloaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
        RaiseEvent UnloadedInput(Me, sender)
    End Sub

    Private Sub shpOutput_Unloaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
        RaiseEvent UnloadedOutput(Me, sender)
    End Sub

    Private Sub shpBlock_CreatedActivator(ByVal sender As Object, ByVal control As clsActivator)
        RaiseEvent CreatedActivator(sender, control)
    End Sub

    Private Sub shpBlock_DeletedActivator(ByVal sender As Object, ByVal control As clsActivator)
        RaiseEvent DeletedActivator(sender, control)
    End Sub

    Private Sub shpBlock_CreatedEvent(ByVal sender As Object, ByVal control As clsEvent)
        RaiseEvent CreatedEvent(sender, control)
    End Sub

    Private Sub shpBlock_DeletedEvent(ByVal sender As Object, ByVal control As clsEvent)
        RaiseEvent DeletedEvent(sender, control)
    End Sub

    Private Sub shpBlock_CreatedInput(ByVal sender As Object, ByVal control As clsInput)
        RaiseEvent CreatedInput(sender, control)
    End Sub

    Private Sub shpBlock_DeletedInput(ByVal sender As Object, ByVal control As clsInput)
        RaiseEvent DeletedInput(sender, control)
    End Sub

    Private Sub shpBlock_CreatedOutput(ByVal sender As Object, ByVal control As clsOutput)
        RaiseEvent CreatedOutput(sender, control)
    End Sub

    Private Sub shpBlock_DeletedOutput(ByVal sender As Object, ByVal control As clsOutput)
        RaiseEvent DeletedOutput(sender, control)
    End Sub

    Private Sub shpBlock_UnloadedActivator(ByVal sender As Object, ByVal control As clsActivator)
        RaiseEvent UnloadedActivator(sender, control)
    End Sub

    Private Sub shpBlock_UnloadedEvent(ByVal sender As Object, ByVal control As clsEvent)
        RaiseEvent UnloadedEvent_(sender, control)
    End Sub

    Private Sub shpBlock_UnloadedInput(ByVal sender As Object, ByVal control As clsInput)
        RaiseEvent UnloadedInput(sender, control)
    End Sub

    Private Sub shpBlock_UnloadedOutput(ByVal sender As Object, ByVal control As clsOutput)
        RaiseEvent UnloadedOutput(sender, control)
    End Sub

    Private Sub shpConnector_ConnectPorts(ByVal sender As Object, ByVal Port1 As shpPort, ByVal Port2 As shpPort)
        RaiseEvent ConnectPorts(sender, Port1, Port2)
    End Sub

    Private Sub shpConnector_DisconnectPorts(ByVal sender As Object, ByVal Port1 As shpPort, ByVal Port2 As shpPort)
        RaiseEvent DisconnectPorts(sender, Port1, Port2)
    End Sub

    Private Sub shpBlock_DoubleClick(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
        If TryCast(e.OriginalSource, Rectangle) IsNot Nothing Then
            RaiseEvent BlockDoubleClick(sender, e)
        End If
    End Sub

    Private Sub shpActivator_DoubleClick(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
        RaiseEvent ActivatorDoubleClick(sender, e)
    End Sub

    Private Sub shpEvent_DoubleClick(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
        RaiseEvent EventDoubleClick(sender, e)
    End Sub

    Private Sub shpInput_DoubleClick(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
        RaiseEvent InputDoubleClick(sender, e)
    End Sub

    Private Sub shpOutput_DoubleClick(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
        RaiseEvent OutputDoubleClick(sender, e)
    End Sub
#End Region
End Class
